import React, { Component } from 'react';
import { Icon, Upload, Modal, message, Button } from 'antd';
import isEqual from 'lodash/isEqual';
import PropTypes from 'prop-types';
import find from 'lodash/find';
import isFunction from 'lodash/isFunction';
import remove from 'lodash/remove';
import findIndex from 'lodash/findIndex';
import request from '@/utils/request';
import styles from './index.less';

// const uploadUrl = 'portal/FileStoreController/upload.do';
// const deleteUrl = 'portal/FileStoreController/delete.do';

class SlickUpload extends Component {
  constructor(props) {
    super(props);

    const { fileList = [] } = props;
    this.state = {
      previewVisible: false,
      previewImage: '',
      fileList,
      prevPropsFileList: fileList,
    };
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    // props.fileList 有更新
    const propsFileList = nextProps.fileList ? nextProps.fileList : [];
    if (!isEqual(propsFileList, prevState.prevPropsFileList)) {
      return {
        ...prevState,
        fileList: propsFileList,
        prevPropsFileList: propsFileList,
      };
    }
    // 返回 null 表示不更新，此函数最后一定需要返回值
    return null;
  }

  getFileList = () => {
    return this.state.fileList;
  };

  renderButton = () => {
    if (this.props.listType === 'picture-card') {
      return (
        <div>
          <Icon type="plus" />
          <div className="ant-upload-text">上传</div>
        </div>
      );
    }
    return (
      <Button>
        <Icon type="plus" />
        上传
      </Button>
    );
  };

  render() {
    const { previewVisible, previewImage, fileList } = this.state;
    const { fileList: ab, deleteUrl, addUrl, onRemove, ...rest } = this.props;
    const { accept, length, size, listType } = rest;
    return (
      <div className={`clearfix ${styles.slickUpload}`}>
        <Upload
          action={addUrl}
          className="slick-upload"
          fileList={fileList}
          onRemove={file => {
            let attachId;

            // 当下上传的
            if (file.response) {
              const {
                response: { success, data },
              } = file;

              if (success === true && Array.isArray(data) && data[0] && data[0].attachId) {
                // eslint-disable-next-line prefer-destructuring
                attachId = data[0].attachId;
              }
            }

            // 通过初始值传入的
            if (file.attachId) {
              // eslint-disable-next-line prefer-destructuring
              attachId = file.attachId;
            }

            if (attachId) {
              return request(deleteUrl, {
                method: 'get',
                data: {
                  attachId,
                },
              }).then(res => {
                const { success, errMessage } = res;
                if (success === true) {
                  message.success('删除成功');
                } else {
                  message.error(errMessage || '删除失败');
                }
              });
            }

            return false;
          }}
          {...rest}
          beforeUpload={file => {
            const ext = `.${file.name.substr(file.name.lastIndexOf('.') + 1)}`;
            const isValidFormat =
              accept
                .split(',')
                .map(val => val.trim())
                .indexOf(ext) !== -1;
            // IE9 不做size判断
            const isSmall = file.size === undefined ? true : file.size < size;
            const isValidLength = fileList.length + 1 <= length;
            if (!isValidFormat) {
              message.error('不支持的文件格式！');
              return false;
            }

            if (!isSmall) {
              message.error('文件太大！');
              return false;
            }

            if (!isValidLength) {
              message.error('已上传文件数量已超过允许的最大个数！');
              return false;
            }

            return true;
          }}
          onPreview={
            listType === 'picture-card'
              ? file => {
                  this.setState({
                    previewImage: find(fileList, { uid: file.uid }).thumbUrl,
                    previewVisible: true,
                  });
                }
              : null
          }
          onChange={({ file, fileList }) => {
            /**
             * 1、remove()会改变原数组
             * 2、状态有：uploading done error removed。每次状态变化都会进这个回调，且fileList都是当下最新的
             * 3、当组件被getFieldDecorator包裹时
             *  a. 会自动传入onChange返回。在新增和删除时，需要主动调用以保证表单获取的该字段会最新的
             *  b. 在指定了valuePropName: 'fileList'时，initialValue会以fileList明挂载到当前组件的props
             *  c. 取值还可通过getValueFromEvent方法，具体参考 https://ant.design/components/form-cn/#components-form-demo-validate-other
             * 4、上传成功时的预期回参[{ docId, docNbr,fileName, fileGetUrl}]。即使多文件上次 每次数组内也只会有一个值
             */

            const { onChange } = this.props;
            const targetIndex = findIndex(fileList, { uid: file.uid });
            if (file.status === 'done' && Array.isArray(file.response)) {
              // TODO 即使开启多选模式
              const { fileGetUrl: url, photoUrl: thumbUrl, docNbr } = file.response[0];
              const isImage = /^image\//.test(file.type);

              // 附件下载链接
              fileList[targetIndex].url = url;
              // 删除需docNbr字段
              fileList[targetIndex].docNbr = docNbr;

              // 如果不是图片，且是 'picture-card' 模式，禁止给thumbUrl和url的赋值，这样预览按钮就会自动禁用
              if (isImage) {
                fileList[targetIndex].thumbUrl = thumbUrl || '';
              } else if (listType === 'picture-card') {
                fileList[targetIndex].url = '';
              }

              if (isFunction(onChange)) {
                onChange(
                  fileList.map(val => {
                    if (Array.isArray(val.response)) {
                      // 提取回参中的有用字段，挂载对象的一级属性上
                      const { docId, docNbr, fileName, fileGetUrl, photoUrl } = val.response[0];
                      return { ...val, docId, docNbr, fileName, fileGetUrl, thumbUrl: photoUrl };
                    }
                    return val;
                  })
                );
              }
            }

            if (file.status === 'error') {
              remove(fileList, item => item.uid === file.uid);
              message.error('文件上传接口，服务异常！');
            }

            if (file.status === 'removed') {
              if (isFunction(onChange)) {
                onChange(
                  fileList.map(val => {
                    if (Array.isArray(val.response)) {
                      // 提取回参中的有用字段，挂载对象的一级属性上
                      const { docId, docNbr, fileName, fileGetUrl, photoUrl } = val.response[0];
                      return {
                        ...val,
                        docId,
                        docNbr,
                        fileName,
                        fileGetUrl,
                        thumbUrl: photoUrl,
                      };
                    }
                    return val;
                  })
                );
              }
            }

            // beforeUpload 返回 false
            if (file.status === undefined) {
              remove(fileList, item => item.uid === file.uid);
            }

            this.setState({ fileList });
          }}
        >
          {fileList.length >= length ? null : this.renderButton()}
        </Upload>

        <Modal
          visible={previewVisible}
          footer={null}
          onCancel={() => this.setState({ previewVisible: false })}
        >
          <img alt="preview" style={{ width: '100%', padding: 16 }} src={previewImage} />
        </Modal>
      </div>
    );
  }
}

SlickUpload.defaultProps = {
  // fileList: [],
  onRemove: () => {},
  length: 999,
  size: 1024 * 1024 * 1024,
  listType: 'text',
  multiple: false,
  accept:
    '.png,.jpg,.jpeg,.gif,.bmp,.txt,.doc,.docx,.xls,.xlsx,.pdf,.ppt,.ogg,.mp4,.mp4,.mpg,.rm,.rmvb,.wmv,.mov,.mkv,.flv,.avi,.rar,.zip',
};

// TODO: fileList没交代清楚
SlickUpload.propTypes = {
  // fileList: PropTypes.arrayOf(PropTypes.object),
  action: PropTypes.string.isRequired,
  deleteUrl: PropTypes.string.isRequired,
  length: PropTypes.number,
  size: PropTypes.number,
  listType: PropTypes.oneOf(['text', 'picture', 'picture-card']),
  accept: PropTypes.string,
  onRemove: PropTypes.func,
  multiple: PropTypes.bool,
};

export default SlickUpload;
